﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Media;
using System.Diagnostics;

namespace Master
{
    public class InterSection : Label
    {
        private iTrafficLightStrategy currentStrategy;
        private Dictionary<Side, List<Road>> roadDictionary = new Dictionary<Side, List<Road>>();
        private TrafficMarshal trafficMarshal;

        public TrafficMarshal getTrafficMarshal()
        {
            return trafficMarshal;
        }

        public void stopStrategy(object sender, EventArgs e)
        {
            currentStrategy.stop();
        }

        public void init(object sender, EventArgs e)
        {
            setupRoadDictionary();
            currentStrategy = TrafficLightStrategyFactory.createTwoWayStrategy();
            if (Background == Brushes.Transparent)
                this.Background = Brushes.Chocolate;
            currentStrategy.start(roadDictionary);
            trafficMarshal = new TrafficMarshal(this);
        }

        private void setupRoadDictionary()
        {
            //Get x and y
            double x = Canvas.GetLeft(this);
            double y = Canvas.GetTop(this);

            //getTopSide
            Point pointer = new Point(x + 1, y - 10);
            roadDictionary.Add(Side.TOP, getRoadsBySide(Side.TOP, pointer));

            //getRightSide
            pointer = new Point(x + Width + 10, y + 1);
            roadDictionary.Add(Side.RIGHT, getRoadsBySide(Side.RIGHT, pointer));

            //getBottomSide
            pointer = new Point(x + 1, y + Height + 10);
            roadDictionary.Add(Side.BOTTOM, getRoadsBySide(Side.BOTTOM, pointer));

            //getLeftSide
            pointer = new Point(x - 10, y + 1);
            roadDictionary.Add(Side.LEFT, getRoadsBySide(Side.LEFT, pointer));
        }

        public List<Road> getRoadsBySide(Side side)
        {
            return roadDictionary[side];
        }

        private List<Road> getRoadsBySide(Side side, Point pointer)
        {
            List<Road> roadList = new List<Road>();
            double startX = pointer.X;
            double startY = pointer.Y;
            Road road;
            switch (side)
            {
                case Side.BOTTOM:
                case Side.TOP:
                    while ((road = findRoad(roadList, pointer)) != null)
                    {
                        roadList.Add(road);
                        pointer.X += road.ActualWidth;
                    }
                    break;
                case Side.LEFT:
                case Side.RIGHT:
                    while ((road = findRoad(roadList, pointer)) != null)
                    {
                        roadList.Add(road);
                        pointer.Y += road.ActualHeight;
                    }
                    break;
            }
            roadList = setupTrafficLights(roadList, side);
            return roadList;
        }

        private Road findRoad(List<Road> roadList, Point pointer)
        {
            Road road = Map.INSTANCE.getRoadAt(pointer);
            if (road != null && !roadList.Contains(road))
                return road;
            return null;
        }

        private List<Road> setupTrafficLights(List<Road> roadList, Side side)
        {
            foreach (Road road in roadList) foreach (Lane lane in road.getLanes())
            {
                if ((side == Side.TOP && lane.Orientation == 180) ||
                    (side == Side.RIGHT && lane.Orientation == 270) ||
                    (side == Side.BOTTOM && lane.Orientation == 0) ||
                    (side == Side.LEFT && lane.Orientation == 90))
                {
                    lane.setTrafficLight(road);
                }
                else //no traffic light --> exit lane
                {
                    lane.Type = LaneType.EXIT;
                }
            }
            return roadList;
        }
    }
}
